package com.zl.quickdoc.utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.ImportDeclaration;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.MarkerAnnotationExpr;
import com.github.javaparser.ast.expr.MemberValuePair;
import com.github.javaparser.ast.expr.NameExpr;
import com.github.javaparser.ast.expr.NormalAnnotationExpr;
import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr;
import com.github.javaparser.ast.stmt.BlockStmt;
import com.github.javaparser.ast.stmt.ReturnStmt;
import com.github.javaparser.ast.stmt.Statement;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import com.github.javaparser.ast.type.Type;
import com.github.javaparser.ast.type.TypeParameter;
import com.zl.quickdoc.constant.QuickDocC;
import com.zl.quickdoc.framework.IApiFramework;
import com.zl.quickdoc.model.ApiAction;
import com.zl.quickdoc.model.ApiField;
import com.zl.quickdoc.model.ApiModule;
import com.zl.quickdoc.model.UriAndMethod;
import com.zl.quickdoc.resolver.JavaSourceFileFactory;
import com.zl.quickdoc.resolver.JavaTypeRegistrar;
import com.zl.quickdoc.resolver.converter.AbstractJavaDocTag;

/**
 * 
 * 解析java源码的代码属性
 *
 * @author zhouliang
 *
 */
public class ParserJavaUtils {
    
    /**
     * 清除包路径
     */
    public static String replacePackageName(String type) {
        type = type.replaceAll("[A-Za-z0-9]+\\.", "");
        return type.replace(" ", "");
    }
    
    /**
     * 默认值示例
     * @param defaultValue
     * @return
     */
    public static String defaultValueHandler(ApiField field) {
        String factType = field.getFactType();
        String defaultValue = field.getDefaultValue();
        if(StringUtils.isBlank(defaultValue)) {
            return "null";
        }
        //一般数值类型
        if(JavaTypeRegistrar.checkNotString(factType)) {
            return defaultValue;
        }
        
        if(field.getSimpleValueFlag()) {
            defaultValue = StringUtils.join(defaultValue.split("[,;，；]"),"\", \"");
        }
        
        return "\""+defaultValue+"\"";
    }
    public static String typeHandler(String factType) {
        if(factType==null){
            return JavaTypeRegistrar.getDefSimpleType();
        }
        factType = replacePackageName(factType);
        
        String factType2 = JavaTypeRegistrar.getSimpleType(factType);
        if(factType2!=null) {
            return factType2;
        }
        if(JavaTypeRegistrar.getShowType(factType) != null) {
            return factType;
        }
        
        return factType;
    }
    public static String isSimpleType(String factType) {
        if(factType == null){
            return JavaTypeRegistrar.getDefSimpleType();
        }
        factType = replacePackageName(factType);
        return JavaTypeRegistrar.getSimpleType(factType);
    }
    
    public static boolean isIgnoreObject(String className) {
        if(StringUtils.isBlank(className)) {
            return false;
        }
        return JavaTypeRegistrar.checkIgnoreClass(className);
    }
    public static String getShowTitle(String title) {
        if(StringUtils.isBlank(title)) {
            return "";
        }
        title = title.split("(\\||:|：)",2)[0];
        if(title.length()>25) {
            title = title.substring(0,25);
        }
        return title;
    }
    /**
     * 获取@orderBy
     */
    public static int getOrderBy(List<AbstractJavaDocTag<?>> docTags) {
        AbstractJavaDocTag<String> tag = JavaTagUtils.findTag(docTags, "@orderBy");
        String orderBy = "0";
        if (tag != null && tag.getValues()!=null) {
            orderBy = tag.getValues();
        }
        try {
           return Integer.valueOf(orderBy);
        }catch(Exception b) {
           return 0;
        }
    }
    
    /**
     * 获取@title
     */
    public static String getTitle(List<AbstractJavaDocTag<?>> docTags,String description,String title) {
        AbstractJavaDocTag<String> tag = JavaTagUtils.findTag(docTags, "@title");
        if (tag != null) {
            return tag.getValues()==null?"未命名":tag.getValues();
        }
        if(StringUtils.isNotBlank(title)){
            return title;
        }
        if(StringUtils.isBlank(description)) {
            return "";
        }
        return description;
    }
    /**
     * 获取@ContentType
     */
    public static String getContentType(List<AbstractJavaDocTag<?>> docTags) {
        AbstractJavaDocTag<String> tag = JavaTagUtils.findTag(docTags, "@contentType");
        return tag != null?tag.getValues():null;
    }
    /**
     * 获取@DataType
     */
    public static String getDataType(List<AbstractJavaDocTag<?>> docTags) {
        AbstractJavaDocTag<String> tag = JavaTagUtils.findTag(docTags, "@dataType");
        return tag != null?tag.getValues():null;
    }
    
    /**
     * 获取@respbody
     */
    public static String getRespbody(List<AbstractJavaDocTag<?>> docTags) {
        AbstractJavaDocTag<String> tag = JavaTagUtils.findTag(docTags, "@respbody");
        return tag != null?tag.getValues():null;
    }

    /**
     * 获取@return
     */
    public static String getReturnDesc(List<AbstractJavaDocTag<?>> docTags) {
        AbstractJavaDocTag<String> tag = JavaTagUtils.findTag(docTags, "@return");
        return tag != null ? tag.getValues() : null;
    }

    /**
     * 获取@param
     */
    public static List<ApiField> getParams(List<AbstractJavaDocTag<?>> docTags) {
        List<AbstractJavaDocTag<ApiField>> tags = JavaTagUtils.findTags(docTags, "@param");
        List<ApiField> list = new ArrayList<>(tags.size());
        for (AbstractJavaDocTag<ApiField> tag : tags) {
            if(tag==null || tag.getValues()==null){
               continue;
            }
            list.add(tag.getValues());
        }
        return list;
    }
    
    /**
     * 获取@paramObj
     */
    public static List<ApiField> getParamObjs(List<AbstractJavaDocTag<?>> docTags) {
        List<AbstractJavaDocTag<ApiField>> tags = JavaTagUtils.findTags(docTags, "@paramObj");
        List<ApiField> list = new ArrayList<>(tags.size());
        for (AbstractJavaDocTag<ApiField> tag : tags) {
            if(tag==null || tag.getValues()==null){
                continue;
            }
            list.add(tag.getValues());
        }
        return list;
    }
    /**
     * 获取@see
     */
    public static ApiField getSeeObj(List<AbstractJavaDocTag<?>> docTags) {
        AbstractJavaDocTag<ApiField> tag = JavaTagUtils.findTag(docTags, "@see");
        return tag != null ? tag.getValues() : null;
    }
    
    /**
     * 获取@resp
     */
    public static List<ApiField> getResp(List<AbstractJavaDocTag<?>> docTags) {
        List<AbstractJavaDocTag<ApiField>> tags = JavaTagUtils.findTags(docTags, "@resp");
        List<ApiField> list = new ArrayList<>(tags.size());
        for (AbstractJavaDocTag<ApiField> tag : tags) {
            if(tag==null || tag.getValues()==null){
                continue;
            }
            list.add(tag.getValues());
        }
        return list;
    }
    
    /** 拼接类名 */
    public static String getWholeClassName(CompilationUnit cu,String className) {
        String packagePath ="";
        if(cu.getPackageDeclaration().isPresent()) {
            packagePath = cu.getPackageDeclaration().get().getNameAsString()+".";
        }
        return packagePath + className;
    }
    /** 获取实现类 */
    public static List<String> getClassForImplemented(CompilationUnit cu) {
        ClassOrInterfaceDeclaration classOrInterface = cu.getType(0).asClassOrInterfaceDeclaration();
        NodeList<ClassOrInterfaceType> types = classOrInterface.getImplementedTypes();
        return getClassFather(cu, types);
    }
    /** 获取继承类 */
    public static List<String> getClassForExtend(CompilationUnit cu) {
        ClassOrInterfaceDeclaration classOrInterface = cu.getType(0).asClassOrInterfaceDeclaration();
        NodeList<ClassOrInterfaceType> types = classOrInterface.getExtendedTypes();
        return getClassFather(cu, types);
    }
    private static List<String> getClassFather(CompilationUnit cu,NodeList<ClassOrInterfaceType> types) {
        if(types==null || types.isEmpty()){
            return null;
        }
        NodeList<ImportDeclaration> importlist = cu.getImports();
        List<String> list = new ArrayList<>();
        for(ClassOrInterfaceType typex:types) {
            String fclazzname = typex.getNameAsString();
            boolean flag = false;
            for(ImportDeclaration importx:importlist){
                String importstr = importx.getNameAsString();
                if(importstr.endsWith("."+fclazzname)){
                    fclazzname = importstr;
                    flag = true;
                    continue;
                }
            }
            if(!flag) {
                fclazzname = ParserJavaUtils.getWholeClassName(cu,fclazzname);
            }
            if("java.io.Serializable".equals(fclazzname)) {
                continue;
            }
            list.add(fclazzname);
        }
        return list;
    }
    /** 获取导入类路径 */
    public static String getClassPackage(CompilationUnit cu,String className) {
        if(isSimpleType(className)!=null) {
            return null;
        }
        if(className.indexOf(".")>-1) {
            return className;
        }
        NodeList<ImportDeclaration> importlist = cu.getImports();
        if(importlist.isNonEmpty()) {
            for(ImportDeclaration importx:importlist) {
                String importstr = importx.getNameAsString();
                if(importstr.endsWith("."+className) || importstr.equals(className)){
                    return importstr;
                }
            }
        }
        return ParserJavaUtils.getWholeClassName(cu,className);
    }

    public static Map<String,Object> getValueAnnotation(Object source,String annotationName) {
        Optional<AnnotationExpr> annonExpr = null;
        if(source instanceof CompilationUnit) {
            CompilationUnit cu = (CompilationUnit) source;
            annonExpr = cu.getType(0).getAnnotationByName(annotationName);
        }else if(source instanceof ClassOrInterfaceDeclaration) {
            ClassOrInterfaceDeclaration cu = (ClassOrInterfaceDeclaration) source;
            annonExpr = cu.getAnnotationByName(annotationName);
        }else if(source instanceof MethodDeclaration) {
            MethodDeclaration cu = (MethodDeclaration) source;
            annonExpr = cu.getAnnotationByName(annotationName);
        }
        else if(source instanceof Parameter) {
            Parameter cu = (Parameter) source;
            annonExpr = cu.getAnnotationByName(annotationName);
        }else if(source instanceof FieldDeclaration) {
            FieldDeclaration cu = (FieldDeclaration) source;
            annonExpr = cu.getAnnotationByName(annotationName);
        }
        Map<String,Object> map = new LinkedHashMap<>();
        if(annonExpr == null || !annonExpr.isPresent()){
             return map;
        }
        
        AnnotationExpr expr = annonExpr.get();
        //System.out.println("   【getValueAnnotation】"+expr.getNameAsString()+"---"+expr.getClass().toString());
        if(expr instanceof SingleMemberAnnotationExpr){//单个无名称参数
            SingleMemberAnnotationExpr tx= expr.asSingleMemberAnnotationExpr();
            Expression val = tx.getMemberValue();
            String key = tx.getNameAsString();
            getExpressionValue(map, key, val);
        }else if(expr instanceof NormalAnnotationExpr){//有名称的参数
            NormalAnnotationExpr t= expr.asNormalAnnotationExpr();
            NodeList<MemberValuePair> list = t.getPairs();
            for(MemberValuePair tx:list){
                Expression val = tx.getValue();
                String key = tx.getNameAsString();
                getExpressionValue(map, key, val);
            }
        }else if(expr instanceof MarkerAnnotationExpr){//无参数
            map.put(expr.getNameAsString(), expr.getNameAsString());//表示有注解
        }
         
        return map;
    }
    private static void getExpressionValue(Map<String,Object> map,String key, Expression val) {
        if(val.isStringLiteralExpr()){
            map.put(key,  val.asStringLiteralExpr().getValue());
        }else if(val.isBooleanLiteralExpr()){
            map.put(key, val.asBooleanLiteralExpr().getValue());
        }else if(val.isIntegerLiteralExpr()){
            map.put(key, val.asIntegerLiteralExpr().getValue());
        }else if(val.isLongLiteralExpr()){
            map.put(key, val.asLongLiteralExpr() .getValue());
        }else if(val.isFieldAccessExpr()){
            map.put(key, val.asFieldAccessExpr().getNameAsString());
        }else if(val.isArrayInitializerExpr()){
            NodeList<Expression> listvals = val.asArrayInitializerExpr().getValues();
            if(listvals.isNonEmpty()){
                List<String> list = new ArrayList<>();
                for(Expression ltx: listvals) {
                    String str = null;
                    if(listvals.get(0).isStringLiteralExpr()){
                        str = ltx.asStringLiteralExpr().getValue();
                    }else if(listvals.get(0).isFieldAccessExpr()){
                        str = ltx.asFieldAccessExpr().getNameAsString();
                    }
                    if(str!=null) {
                        list.add(str);
                    }
                }
                map.put(key, list);
            }
        }
    }
    
    /** 解析接口方法信息 */
    public static ApiModule analysisApiModule(List<CompilationUnit> list,JavaSourceFileFactory ist
            ,IApiFramework framework) {
        if(list.isEmpty()) {
            return null;
        }
        Collections.reverse(list);
        
        ApiModule apiModule = new ApiModule();
        List<ApiAction> apiActions = new ArrayList<>();
        apiModule.setApiActions(apiActions);
        for(int i=0; i<list.size();i++){
            CompilationUnit cu = list.get(i);
            try {
                ClassOrInterfaceDeclaration cid = cu.getType(0).asClassOrInterfaceDeclaration();
                String className = getWholeClassName(cu, cid.getNameAsString());
                if(i==list.size()-1) {
                    System.out.println("【解析接口】" + className);
                }
                apiModule.setJavaUnit(cu);
                if(cu.getPackageDeclaration().isPresent()) {
                    apiModule.setPackagePath(cu.getPackageDeclaration().get().toString());
                }
                apiModule.setClassName(className);
                apiModule.setSimpleName(cid.getNameAsString());
                String clzcomment="";
                if(cid.getComment().isPresent()) {
                    clzcomment = cid.getComment().get().getContent().replace("\r\n", "\n");
                }
                if(StringUtils.isNotBlank(clzcomment)) {
                    List<String> comments = CommentUtils.asCommentList(clzcomment);
                    List<AbstractJavaDocTag<?>> docTagList = JavaTagUtils.docTagHandler(comments);
                    if(JavaTagUtils.findTag(docTagList, "@ignore")!=null) {
                        apiModule.setHiddenFlag(true);
                    }
                    if(apiModule.getSimpleName().equals(apiModule.getTitle())) {
                        apiModule.setTitle("");
                    }
                    apiModule.setDescription(CommentUtils.parseCommentText(clzcomment));
                    apiModule.setDocTags(docTagList);
                    apiModule.setTitle(getTitle(docTagList, apiModule.getDescription(), apiModule.getTitle()));
                    apiModule.setOrderBy(getOrderBy(apiModule.getDocTags()));
                }
                if(StringUtils.isBlank(apiModule.getDescription())){
                    apiModule.setDescription("");
                }
                if(StringUtils.isBlank(apiModule.getTitle())){
                    apiModule.setTitle(apiModule.getSimpleName());
                }
                Map<String, Object> anonMap = getValueAnnotation(cid, "Api");
                if(!anonMap.isEmpty()) {
                    if(anonMap.get("hidden")!=null && (boolean)anonMap.get("hidden")) {
                        apiModule.setHiddenFlag(true);
                    }
                    String t = (String)anonMap.get("Api");
                    if(t != null && !"Api".equals(t)) {
                        apiModule.setTitle(t);
                    }
                    t = (String)anonMap.get("value");
                    if(StringUtils.isNotBlank(t)) {
                        apiModule.setTitle(t);
                    }
                    t = (String)anonMap.get("tags");
                    if(StringUtils.isNotBlank(t)) {
                        apiModule.setTitle(t);
                    }
                }
                apiModule.setTitle(getShowTitle(apiModule.getTitle()));
                List<MethodDeclaration> methods = cid.getMethods();
                for(MethodDeclaration md:methods){
                    if(!md.isStatic() && md.isPublic()) {
                        analysisApiAction(i,apiModule,md,framework, ist);
                    }
                }
            } catch (Exception e) {
               e.printStackTrace();
            }
        }
        if(apiModule.getHiddenFlag()) {
            return null;
        }
        
        Iterator<ApiAction> apis = apiModule.getApiActions().iterator();
        ApiAction apix;
        while(apis.hasNext()) {
           apix = apis.next();
           if(apix.getHiddenFlag() || apix.getUris()==null || apix.getUris().isEmpty()
                   || apix.getMethods()==null || apix.getMethods().isEmpty()) {
               apis.remove();
           }else {
               if(apix.getReqParam() != null) {
                   handleIgnoreParam(apix.getReqParam());
               }
               if(apix.getResParam() != null) {
                   handleIgnoreParam(apix.getResParam());
               }
           }
        }
        if(apiModule.getApiActions().isEmpty()) {
            return null;
        }
        
        return apiModule;
    }
        
    private static void analysisApiAction(int i,ApiModule apiModule,MethodDeclaration md, IApiFramework framework
            ,JavaSourceFileFactory ist) {
        String className = apiModule.getClassName();
        List<ApiAction> apiActions = apiModule.getApiActions();
        
        String methodName = md.getNameAsString();
        com.github.javaparser.ast.type.Type elementType = md.getType();
        NodeList<Parameter> parameters = md.getParameters();
        String returnType = elementType.asString();
        
        List<ApiField> resParam = new ArrayList<>();
        ApiField resParamVO = handleParamType(elementType, null);
        boolean responseListFlag = false;
        if(resParamVO != null) {
            resParamVO.setRequire(true);
            resParamVO.setAnonymousFlag(true);
            responseListFlag = "Arrays".equals(resParamVO.getFactType());
            resParam.add(resParamVO);
        }
        
        List<String> paramTypes = new ArrayList<>();
        boolean requestJsonFlag = false;
        boolean requestListFlag = false;
        List<ApiField> reqParam = new ArrayList<>();//入参
        Map<String, ApiField> paramsFactNameMap = new LinkedHashMap<>();
        Map<String, Object> anonMap;
        for(Parameter px:parameters) {
            String pname = px.getNameAsString();
            Type type = px.getType();
            paramTypes.add(replacePackageName(type.asString()));
            
            String tpackage = getClassPackage(apiModule.getJavaUnit(), type.asString());
            if(isIgnoreObject(tpackage) && !JavaTypeRegistrar.checkFileType(replacePackageName(tpackage))) {
                continue;
            }
            
            String showName = null;
            boolean requiredFlag = false;
            boolean pathFlag = false;
            boolean anonymousFlag=false; 
            anonMap = getValueAnnotation(px, "RequestBody");
            if(!anonMap.isEmpty()) {
                requestJsonFlag = true;
                anonymousFlag = true;
            }
            String annokey = "PathVariable";
            anonMap = getValueAnnotation(px, annokey);
            if(anonMap.isEmpty()) {
                annokey = "RequestParam";
                anonMap = getValueAnnotation(px, annokey);
            }else {
                pathFlag = true;
            }
            if(!anonMap.isEmpty()) {
                if(anonMap.get("required")!=null){
                    requiredFlag = (boolean)anonMap.get("required");
                }
                String t = (String) anonMap.get(annokey);
                if(StringUtils.isNotBlank(t) && !annokey.equals(t)) {
                    showName = (String)anonMap.get(annokey);
                }
                t = (String) anonMap.get("value");
                if(StringUtils.isNotBlank(t)) {
                    showName = t;
                }
            }
            anonMap = getValueAnnotation(px, "ModelAttribute");
            if(!anonMap.isEmpty()) {
            }
            if(StringUtils.isBlank(showName)) {
                showName = pname;
            }
            
            ApiField pvo = handleParamType(type,null);
            requestListFlag = "Arrays".equals(pvo.getFactType());
            paramsFactNameMap.put(pname, pvo);
            reqParam.add(pvo);
            pvo.setName(showName);
            pvo.setFactName(pname);
            pvo.setPathFlag(pathFlag);
            pvo.setRequire(requiredFlag);
            if(anonymousFlag || "Objects".equals(pvo.getFactType())) {
                pvo.setAnonymousFlag(true);
                if(!anonymousFlag && "Objects".equals(pvo.getFactType())) {
                    pvo.setMergeObjFlag(true);
                }
            }
            
            String pxcomment = "";
            if(px.getComment().isPresent()) {
                pxcomment = px.getComment().get().getContent().replace("\r\n", "\n");
            }
            if(StringUtils.isNotBlank(pxcomment)) {
                List<String> comments = CommentUtils.asCommentList(pxcomment);
                List<AbstractJavaDocTag<?>> docTagList = JavaTagUtils.docTagHandler(comments);
                if(JavaTagUtils.findTag(docTagList, "@ignore")!=null) {
                    pvo.setHiddenFlag(true);
                }
                pvo.setDescription(CommentUtils.parseCommentText(pxcomment));
                pvo.setDocTags(docTagList);
                pvo.setTitle(getTitle(docTagList, pvo.getDescription(), pvo.getTitle()));
            }
            if(StringUtils.isBlank(pvo.getDescription())){
                pvo.setDescription("");
            }
            if(StringUtils.isBlank(pvo.getTitle())){
                pvo.setTitle("");
            }
        }
        String paramType = StringUtils.join(paramTypes,",");
        
        ApiAction apiAction = null;
        if(i>0) {
            for(ApiAction apix:apiActions) {
                if(methodName.equals(apix.getSimpleName()) && returnType.equals(apix.getReturnTypeStr()) && paramType.equals(apix.getParamTypeStr())) {
                    apiAction = apix;
                    break;
                }
            }
        }
        if(apiAction == null) {
            apiAction = new ApiAction();
            apiActions.add(apiAction);
        }
        if(!requestJsonFlag) {
            List<ApiField> reqParam2 = reqParam;
            reqParam = new ArrayList<>();
            ApiField vo = new ApiField();
            vo.setName(QuickDocC.DEF_KEY_OBJECT);
            vo.setShowType("Objects");
            vo.setFactType(vo.getShowType());
            vo.setChildren(reqParam2);
            reqParam.add(vo);
        }
        apiAction.setReqParam(reqParam);
        apiAction.setResParam(resParam);
        apiAction.setName(className+"."+methodName);
        apiAction.setSimpleName(methodName);
        apiAction.setMethodDeclaration(md);
        apiAction.setParamTypeStr(paramType);
        apiAction.setReturnTypeStr(returnType);
        String comment = "";
        if (md.getComment().isPresent()) {
            comment = md.getComment().get().getContent().replace("\r\n", "\n");
        }
        if(StringUtils.isNotBlank(comment)) {
            List<String> comments = CommentUtils.asCommentList(comment);
            List<AbstractJavaDocTag<?>> docTagList = JavaTagUtils.docTagHandler(comments);
            if(JavaTagUtils.findTag(docTagList, "@ignore")!=null) {
                apiAction.setHiddenFlag(true);
            }
            apiAction.setDescription(CommentUtils.parseCommentText(comment));
            apiAction.setDocTags(docTagList);
            if(methodName.equals(apiAction.getTitle())) {
                apiAction.setTitle("");
            }
            apiAction.setTitle(getTitle(docTagList, apiAction.getDescription(), apiAction.getTitle()));
            apiAction.setOrderBy(getOrderBy(docTagList));
        }
        if(StringUtils.isBlank(apiAction.getDescription())){
            apiAction.setDescription("");
        }
        if(StringUtils.isBlank(apiAction.getTitle())){
            apiAction.setTitle(methodName);
        }
        apiAction.setOrderBy(getOrderBy(apiAction.getDocTags()));
        apiAction.setTitle(getTitle(apiAction.getDocTags(),apiAction.getDescription(),apiAction.getTitle()));
        apiAction.setRespbody(getRespbody(apiAction.getDocTags()));
        apiAction.setReturnDesc(getReturnDesc(apiAction.getDocTags()));
        
        boolean responseJsonFlag = framework.checkReturnJson(apiModule.getJavaUnit(), md);
        UriAndMethod urisAndMethods = framework.getUrisAndMethods(apiModule.getJavaUnit(), md);
        if(urisAndMethods!=null) {
            apiAction.setUris(urisAndMethods.getUris());
            apiAction.setMethods(urisAndMethods.getMethods());
            if(urisAndMethods.getConsumes()!=null && !urisAndMethods.getConsumes().isEmpty()) {
                apiAction.setContentType(urisAndMethods.getConsumes().toString());
            }
            if(urisAndMethods.getProduces()!=null && !urisAndMethods.getProduces().isEmpty()) {
                apiAction.setDataType(urisAndMethods.getProduces().toString());
            }
        }
        
        if(requestJsonFlag) {
            apiAction.setRequestJsonFlag(requestJsonFlag);
            apiAction.setContentType(QuickDocC.TYPE_JSON);
        }
        if(responseJsonFlag) {
            apiAction.setResponseJsonFlag(responseJsonFlag);
            apiAction.setDataType(QuickDocC.TYPE_JSON);
        }
        if(requestListFlag) {
            apiAction.setRequestListFlag(requestListFlag);
        }
        if(responseListFlag) {
            apiAction.setResponseListFlag(responseListFlag);
        }
        anonMap = getValueAnnotation(md, "ApiOperation");
        if(!anonMap.isEmpty()) {
            if(anonMap.get("hidden")!=null && (boolean)anonMap.get("hidden")) {
                apiAction.setHiddenFlag(true);
            }
            String t = (String)anonMap.get("consumes");
            if(StringUtils.isNotBlank(t)) {//请求
                apiAction.setContentType(t);
            }
            t = (String)anonMap.get("produces");
            if(StringUtils.isNotBlank(t)) {//返回
                apiAction.setDataType(t);
            }
            t = (String)anonMap.get("Api");
            if(StringUtils.isNotBlank(t) && !"Api".equals(t)) {
                apiAction.setTitle(t);
            }
            t = (String)anonMap.get("value");
            if(StringUtils.isNotBlank(t)) {
                apiAction.setTitle(t);
            }
        }
        if(!apiAction.getHiddenFlag()) {
            getChildrenFields(apiModule, reqParam, ist,0, apiModule.getJavaUnit());
            getChildrenFields(apiModule, resParam, ist,0, apiModule.getJavaUnit());
        }
        handleMergeParamTag(apiAction,paramsFactNameMap);
        
        boolean requestVoid = reqParam.isEmpty();
        boolean responseVoid = elementType.isVoidType() && resParam.isEmpty();
        if(requestVoid){
            apiAction.setRequestVoid(requestVoid);
        }
        if(responseVoid){
            apiAction.setResponseVoid(responseVoid);
        }
        apiAction.setTitle(getShowTitle(apiAction.getTitle()));
    }
    
    /** 解析对象字段信息 */
    public static ApiField analysisApiField(List<CompilationUnit> list,JavaSourceFileFactory ist,Optional<NodeList<Type>> factTypeArguments) {
        if(list.isEmpty()) {
            return null;
        }
        Collections.reverse(list);
        
        ApiField obj = new ApiField();
        List<ApiField> fieldInfos = new ArrayList<>();
        obj.setChildren(fieldInfos);
        for(int i=0; i<list.size();i++){
            CompilationUnit cu = list.get(i);
            try {
                ClassOrInterfaceDeclaration cid = cu.getType(0).asClassOrInterfaceDeclaration();
                String className = getWholeClassName(cu, cid.getNameAsString());
                
                obj.setClassName(className);
                obj.setSimpleName(cid.getNameAsString());
                obj.setShowType(obj.getSimpleName());
                obj.setFactType(obj.getSimpleName());
                String clzcomment="";
                if(cid.getComment().isPresent()) {
                    clzcomment = cid.getComment().get().getContent().replace("\r\n", "\n");
                }
                if(StringUtils.isNotBlank(clzcomment)) {
                    List<String> comments = CommentUtils.asCommentList(clzcomment);
                    List<AbstractJavaDocTag<?>> docTagList = JavaTagUtils.docTagHandler(comments);
                    obj.setDescription(CommentUtils.parseCommentText(clzcomment));
                    obj.setDocTags(docTagList);
                    obj.setTitle(getTitle(docTagList, obj.getDescription(), obj.getTitle()));
                }
                if(StringUtils.isBlank(obj.getDescription())){
                    obj.setDescription("");
                }
                if(StringUtils.isBlank(obj.getTitle())){
                    obj.setTitle("");
                }
                Map<String, Object> anonMap = getValueAnnotation(cid, "ApiModel");
                if(!anonMap.isEmpty()) {
                    String t = (String) anonMap.get("ApiModel");
                    if(StringUtils.isNotBlank(t) && !"ApiModel".equals(t)) {
                        obj.setTitle(t);
                    }
                    t = (String) anonMap.get("value");
                    if(StringUtils.isNotBlank(t)) {
                        obj.setTitle(t);
                    }
                }
                
                Map<String, Type> paramsMap = new LinkedHashMap<>();
                if(factTypeArguments!=null && factTypeArguments.isPresent()) {
                    NodeList<TypeParameter> typeArguments = cid.getTypeParameters();
                    for(int ti=0; ti<typeArguments.size();ti++){
                        Type ftype = factTypeArguments.get().get(ti);
                        paramsMap.put(replacePackageName(typeArguments.get(ti).getNameAsString()), ftype);
                    }
                }
                
                List<FieldDeclaration> fields = cid.getFields();
                for(FieldDeclaration fd:fields){
                    String name = fd.getVariable(0).getName().asString();
                    if("serialVersionUID".equals(name)) {
                        continue;
                    }
                    com.github.javaparser.ast.type.Type elementType = fd.getElementType();
                    boolean existFlag = false;
                    List<MethodDeclaration> methods = cid.getMethodsByName("get"+StringUtils.capitalize(name));
                    if(methods.isEmpty()) {
                        methods = cid.getMethodsByName("is"+StringUtils.capitalize(name));
                    }
                    if(methods.isEmpty()) {
                        existFlag = false;
                    }else {
                        for(MethodDeclaration methodx:methods) {
//                            com.github.javaparser.ast.type.Type returnType = methodx.getType();
                            java.util.Optional<BlockStmt> body = methodx.getBody();
                            if(body.isPresent()) {
                                BlockStmt bs = body.get();
                                Statement st = bs.getStatement(0);
                                String fname = null;
                                if(st instanceof ReturnStmt) {//get
                                    ReturnStmt st1 = st.asReturnStmt();
                                    if(st1.getExpression().isPresent()) {
                                        if(st1.getExpression().get() instanceof NameExpr) {
                                            fname = st1.getExpression().get().asNameExpr().getNameAsString();
                                        }
                                    }
                                }
//                                else if(st instanceof ExpressionStmt) {//set
//                                }
                                if(name.equals(fname)) {
                                    existFlag = true;
                                    break;
                                }
                            }
                        }
                    }
                    if(!existFlag) {
                        continue;
                    }
                    ApiField ptfield = handleParamType(elementType,paramsMap);
                    
                    ApiField field = null;
                    if(i>0) {
                        for(ApiField fieldx:fieldInfos) {
                            if(name.equals(fieldx.getFactName()) && ptfield.getClassName().equals(fieldx.getClassName())) {
                                field = fieldx;
                                break;
                            }
                        }
                    }
                    if(field == null) {
                        field = new ApiField();
                        fieldInfos.add(field);
                    }
                    field.setChildren(ptfield.getChildren());
                    field.setSimpleValueFlag(ptfield.getSimpleValueFlag());
                    field.setParamType(ptfield.getParamType());
                    field.setClassName(ptfield.getClassName());
                    field.setSimpleName(ptfield.getSimpleName());
                    field.setShowType(ptfield.getShowType());
                    field.setFactType(ptfield.getFactType());
                    field.setName(name);
                    field.setFactName(name);
                    
                    String comment = "";
                    if(fd.getComment().isPresent()) {
                        comment = fd.getComment().get().getContent().replace("\r\n", "\n");
                    }
                    if(StringUtils.isNotBlank(comment)) {
                        List<String> comments = CommentUtils.asCommentList(comment);
                        List<AbstractJavaDocTag<?>> docTagList = JavaTagUtils.docTagHandler(comments);
                        if(JavaTagUtils.findTag(docTagList, "@ignore")!=null) {
                            field.setHiddenFlag(true);
                        }
                        field.setDescription(CommentUtils.parseCommentText(comment));
                        field.setDocTags(docTagList);
                        field.setTitle(getTitle(docTagList, field.getDescription(), field.getTitle()));
                    }
                    if(StringUtils.isBlank(field.getDescription())){
                        field.setDescription("");
                    }
                    if(StringUtils.isBlank(field.getTitle())){
                        field.setTitle("");
                    }
                    anonMap = getValueAnnotation(fd, "JsonIgnore");
                    if(!anonMap.isEmpty()) {
                        field.setHiddenFlag(true);
                    }
                    
                    anonMap = getValueAnnotation(fd, "ApiModelProperty");
                    String swtitle="";
                    String swval=""; 
                    String swdesc="";
                    if(!anonMap.isEmpty()) {
                        if(anonMap.get("hidden")!=null && (boolean)anonMap.get("hidden")){
                            field.setHiddenFlag(true);
                        }
                        if(anonMap.get("required")!=null && (boolean)anonMap.get("required")) {
                            field.setRequire(true);
                        }
                        String t = (String) anonMap.get("ApiModelProperty");
                        if(StringUtils.isNotBlank(t) && !"ApiModelProperty".equals(t)) {
                            swtitle = t;
                        }
                        t = (String)anonMap.get("value");
                        if(StringUtils.isNotBlank(t)) {
                            swtitle = t;
                        }
                        t = (String)anonMap.get("example");
                        if(StringUtils.isNotBlank(t)) {
                            swval = t;
                        }
                        t = (String)anonMap.get("notes");
                        if(StringUtils.isNotBlank(t)) {
                            swdesc = t;
                        }
                    }
                    
                    //支持常用必填注解
                    if(!getValueAnnotation(fd, "NotBlank").isEmpty() || !getValueAnnotation(fd, "NotNull").isEmpty() ||
                            !getValueAnnotation(fd, "NotEmpty").isEmpty()){
                        field.setRequire(true);
                    }
                    
                    anonMap = getValueAnnotation(fd, "JsonProperty");
                    if(!anonMap.isEmpty()) {
                        String showname = (String)anonMap.get("JsonProperty");
                        if(StringUtils.isNotBlank(showname) && !"JsonProperty".equals(showname)) {
                            field.setName(showname);
                        }
                        showname = (String)anonMap.get("value");
                        if(StringUtils.isNotBlank(showname)) {
                            field.setName(showname);
                        }
                    }
                    comment = field.getDescription();
                    
                    boolean hasCommentFlag = StringUtils.isNotBlank(comment);
                    if (!hasCommentFlag && StringUtils.isNotBlank(swdesc)) {
                        hasCommentFlag = true;
                        comment = swdesc;
                    }else if (!hasCommentFlag && StringUtils.isNotBlank(swtitle)) {
                        hasCommentFlag = true;
                        comment = swtitle;
                    }
                    
                    if (!hasCommentFlag) {
                        field.setDescription("");
                        field.setTitle("");
                        field.setDefaultValue(swval);
                    } else {
                        String title = StringUtils.isNotBlank(swtitle)?swtitle:field.getTitle();
                        
                        List<AbstractJavaDocTag<?>> docTagList = field.getDocTags();
                        AbstractJavaDocTag<String> titleTag = JavaTagUtils.findTag(docTagList, "@title");
                        if (titleTag != null) {
                            title = titleTag.getValues();
                        }
                        String defaultValue = title;
                        //值说明、示例值
                        if(defaultValue.contains("|")) {
                           String[] vals=defaultValue.split("\\|");
                           if(vals.length==2) {
                               if(!QuickDocC.YES_ZH.equals(vals[1]) &&!QuickDocC.YES_EN.equalsIgnoreCase(vals[1])
                                      && !QuickDocC.NOT_ZH.equals(vals[1]) && !QuickDocC.NOT_EN.equalsIgnoreCase(vals[1])) {
                                   defaultValue=vals[1];
                               }else {
                                   defaultValue = null;
                               }
                           }else if(vals.length>2) {
                               defaultValue=vals[2];
                           }else {
                               defaultValue = null;
                           }
                        }else {
                            defaultValue = null;
                        }
                        if(StringUtils.isNotBlank(swval)) {
                            defaultValue = swval;
                        }
                        boolean requireFlag = field.getRequire();
                        if(!requireFlag) {
                            Pattern p = Pattern.compile("(\\||^) *(" + QuickDocC.YES_ZH+"|"+QuickDocC.YES_EN+")\\b *(\\||$)", Pattern.CASE_INSENSITIVE);
                            Matcher m = p.matcher(comment);
                            if(m.find()) {
                                requireFlag = true;
                                comment = m.replaceFirst(m.group().startsWith("|")&&m.group().endsWith("|")?"|":"");
                            }else {
                               m = p.matcher(title);
                               if(m.find()) {
                                   requireFlag = true;
                                   title = m.replaceFirst(m.group().startsWith("|")&&m.group().endsWith("|")?"|":"");
                               }
                            }
                        }
                        if(comment.contains("|")) {
                            comment = comment.replaceAll("\\|("+QuickDocC.YES_EN+"|"+QuickDocC.YES_EN+"|"+QuickDocC.NOT_EN+"|"+QuickDocC.NOT_EN+")$","");
                        }
                        String title2=title;
                        if(title.contains("|")) {
                            title = title.split("\\|")[0];
                        }
                        field.setTitle(title.length()>25?title.substring(0,25):title);
                        field.setDescription(comment);
                        if(StringUtils.isNotBlank(title2) && StringUtils.isBlank(comment)) {
                            field.setDescription(title2);
                        }
                        else if(StringUtils.isNotBlank(title2) && !comment.startsWith(title)) {
                            field.setDescription(title2+"："+ comment);
                        }
                        field.setRequire(requireFlag);
                        field.setDefaultValue(defaultValue);
                    }
                }
            } catch (Exception e) {
               e.printStackTrace();
            }
        }
        return obj;
    }

    private static void getChildrenFields(ApiModule apiModule, List<ApiField> fields, JavaSourceFileFactory ist, int idx,CompilationUnit javaUnit) {
        if(fields == null || fields.isEmpty()) {
            return;
        }
        if(idx<=1) {
            Iterator<ApiField> iterator = fields.iterator();
            List<ApiField> clist = null;
            while(iterator.hasNext()) {
                ApiField field = iterator.next();
                if("Objects".equals(field.getFactType()) && field.getMergeObjFlag() && field.getParamType()!=null) {
                    ClassOrInterfaceType clztype = field.getParamType().asClassOrInterfaceType();
                    String tpackage = getClassPackage(javaUnit, clztype.getNameAsString());
                    List<CompilationUnit> fieldUints = ist.getSelfFatherClass(tpackage);
                    if(fieldUints.isEmpty()) {
                        tpackage = getClassPackage(apiModule.getJavaUnit(), clztype.getNameAsString());
                        fieldUints = ist.getSelfFatherClass(tpackage);
                    }
                    ApiField cfield = analysisApiField(fieldUints, ist, clztype.getTypeArguments());
                    if(cfield != null) {
                        clist = cfield.getChildren();
                        CompilationUnit javaUnit2 = fieldUints.get(0);
                        clist.stream().forEach(f->f.setJavaUnit(javaUnit2));//内部使用父级
                    }
                    iterator.remove();
                }
            }
            
            if(clist!=null && !clist.isEmpty()) {
                for(ApiField x:clist) {
                    if(fields.stream().noneMatch(y->y.getName().equals(x.getName()))) {
                        fields.add(x);
                    }
                }
            }
        }
        idx++;
    
        for(ApiField field:fields) {
            field.setTitle(getShowTitle(field.getTitle()));
            if(StringUtils.isBlank(field.getName()) || field.getAnonymousFlag()) {
                if("Objects".equals(field.getFactType()) || "Map".equals(field.getFactType()) ) {
                    field.setName(QuickDocC.DEF_KEY_OBJECT);
                } else if("Arrays".equals(field.getFactType())) {
                    field.setName(QuickDocC.DEF_KEY_LIST);
                }else if(StringUtils.isBlank(field.getName())){
                    field.setName("");//数组内部是值的
                }
            }
            Type type = field.getParamType();
            if(type==null) {//非json
                getChildrenFields(apiModule, field.getChildren(), ist, idx, javaUnit);
            }
            else if(field.getChildren()!=null && !field.getChildren().isEmpty()) {
                getChildrenFields(apiModule, field.getChildren(), ist, idx, javaUnit);
            }
            else if("Map".equals(field.getFactType())) {
                getChildrenFields(apiModule, field.getChildren(), ist, 0, javaUnit);
            }
            else if("Objects".equals(field.getFactType())) {
                ClassOrInterfaceType clztype = type.asClassOrInterfaceType();
                String tpackage = getClassPackage(javaUnit, clztype.getNameAsString());
                List<CompilationUnit> fieldUints = ist.getSelfFatherClass(tpackage);
                if(fieldUints.isEmpty()) {
                    tpackage = getClassPackage(apiModule.getJavaUnit(), clztype.getNameAsString());
                    fieldUints = ist.getSelfFatherClass(tpackage);
                }
                if(!fieldUints.isEmpty()) {
                    field.setJavaUnit(fieldUints.get(0));
                }
                ApiField cfield = analysisApiField(fieldUints, ist, clztype.getTypeArguments());
                if(cfield != null) {
                    if(StringUtils.isBlank(field.getTitle())) {
                        field.setTitle(cfield.getTitle());
                        field.setDescription(cfield.getDescription());
                    }else if(StringUtils.isNotBlank(field.getTitle()) && StringUtils.isNotBlank(cfield.getTitle())) {
                        field.setTitle(field.getTitle() + String.format(QuickDocC.GENERIC_OBJECT_FORMAT,cfield.getTitle()));
                    }
                    field.setChildren(cfield.getChildren());
                    if(field.getChildren()==null || field.getChildren().stream().noneMatch(x->x.getSimpleName().equals(field.getSimpleName()))) {
                        getChildrenFields(apiModule, field.getChildren(), ist, idx, field.getJavaUnit());
                    }
                }
            }else if("Arrays".equals(field.getFactType())) {
                ApiField pvo = handleParamType(field.getParamType(), null);
                List<ApiField> children = new ArrayList<>();
                children = new ArrayList<>();
                children.add(pvo);
                field.setJavaUnit(field.getJavaUnit()!=null?field.getJavaUnit():javaUnit);
                field.setChildren(children);
                getChildrenFields(apiModule, field.getChildren(), ist, idx, field.getJavaUnit());
                
                List<ApiField> children2 = field.getChildren();
                while(children2!=null && !children2.isEmpty()  && ("Objects".equals(children2.get(0).getFactType()) || "Arrays".equals(children2.get(0).getFactType()))) {
                    if(StringUtils.isNotBlank(field.getTitle()) && StringUtils.isNotBlank(children2.get(0).getTitle())) {
                        field.setTitle(field.getTitle()+String.format(QuickDocC.GENERIC_OBJECT_FORMAT,children2.get(0).getTitle()));
                        children2 = null;
                    }else if(StringUtils.isBlank(field.getTitle()) && StringUtils.isNotBlank(children2.get(0).getTitle())) {
                        field.setTitle(children2.get(0).getTitle());
                        children2 = null;
                    }else {
                        children2 = children2.get(0).getChildren();
                    }
                }
            }
            if(field.getSimpleValueFlag() && field.getChildren()!=null && !field.getChildren().isEmpty()) {
                ApiField childrenx = field.getChildren().get(0);
                childrenx.setSimpleValueFlag(true);
                childrenx.setDefaultValue(field.getDefaultValue());
            }
        }
    }
    public static ApiField handleParamType(Type type, Map<String, Type> paramsMap) {
        if(type.isVoidType()) {
            return null;
        }
        ApiField field = new ApiField();
        String pclassName = type.asString();
        String psimpleName = replacePackageName(pclassName); 
        String showType = "";
        if("Object".equals(psimpleName)){
            showType = "None";
        }
        else if(type.isPrimitiveType()) {
            psimpleName = replacePackageName(type.asPrimitiveType().asString());
            showType = psimpleName;
        }
        else if(type.isArrayType()) {
            psimpleName = replacePackageName(type.asArrayType().getElementType().asString());
            Type eltype = type.getElementType();
            showType = "Arrays";
            if(eltype.isClassOrInterfaceType()) {
                type = eltype;
                if(isSimpleType(replacePackageName(psimpleName))!=null || JavaTypeRegistrar.checkFileType(replacePackageName(psimpleName))) {
                    field.setSimpleValueFlag(true);
                }
            }
        }else if(type.isClassOrInterfaceType()) {
            ClassOrInterfaceType clztype = type.asClassOrInterfaceType();
            if(JavaTypeRegistrar.checkMapType(replacePackageName(psimpleName))) {
                showType = "Map";
                Optional<NodeList<Type>> tt = clztype.getTypeArguments();
                if(tt.isPresent()) {
                    Type ts1 = tt.get().get(0);
                    String cname=ts1.asString();
                    String sname=replacePackageName(cname);
                    ApiField field1 = new ApiField();
                    field1.setParamType(ts1);
                    field1.setName("xxx");
                    field1.setFactName("xxx");
                    field1.setTitle("Map<键 , 值>");
                    field1.setDescription(field1.getTitle());
                    field1.setClassName(cname);
                    field1.setSimpleName(sname);
                    field1.setShowType(replacePackageName(sname));
                    field1.setFactType(field1.getShowType());
                    field.setChildren(Arrays.asList(field1));
                    
                    ts1 = tt.get().get(1);
                    cname=ts1.asString();
                    sname=replacePackageName(cname);
                    ApiField field2 = new ApiField();
                    field2.setParamType(ts1);
                    field2.setClassName(cname);
                    field2.setSimpleName(sname);
                    if(ts1.isClassOrInterfaceType()) {
                        ClassOrInterfaceType clzts2 = ts1.asClassOrInterfaceType();
                        if(isSimpleType(replacePackageName(clzts2.getNameAsString()))!=null || JavaTypeRegistrar.checkFileType(replacePackageName(clzts2.getNameAsString()))) {
                            field2.setShowType(replacePackageName(clzts2.getNameAsString()));
                            field2.setFactType(field2.getShowType());
                        }else {
                            field2.setShowType("Objects");
                            field2.setFactType(field2.getShowType());
                            field2.setMergeObjFlag(true);
                        }
                    }else {
                        field2.setShowType(sname);
                        field2.setFactType(field2.getShowType());
                    }
                    field1.setChildren(Arrays.asList(field2));
                }
            } else if(JavaTypeRegistrar.checkListType(replacePackageName(psimpleName))) {
                showType = "Arrays";
                Optional<NodeList<Type>> ts = clztype.getTypeArguments();
                if(ts.isPresent() && ts.get().get(0).isClassOrInterfaceType()) {
                    clztype = clztype.getTypeArguments().get().get(0).asClassOrInterfaceType();
                    type = clztype;
                    psimpleName = clztype.getNameAsString();
                    if(isSimpleType(replacePackageName(psimpleName))!=null || JavaTypeRegistrar.checkFileType(replacePackageName(psimpleName))) {
                        field.setSimpleValueFlag(true);
                    }else if(!JavaTypeRegistrar.checkListType(replacePackageName(psimpleName)) && paramsMap!=null){
                        Type type2 = paramsMap.get(replacePackageName(type.asString()));
                        if(type2!=null) {
                            type = type2;
                        }
                    }
                }
            } else {
                psimpleName = replacePackageName(type.asClassOrInterfaceType().getNameAsString());
                if(JavaTypeRegistrar.checkFileType(replacePackageName(pclassName))) {
                    showType = "File";
                    field.setSimpleValueFlag(true);
                }else if(isSimpleType(psimpleName)==null) {
                    showType = "Objects";
                    if(paramsMap != null) {
                        Type ftype = paramsMap.get(replacePackageName(type.asString()));
                        if(ftype!=null) {
                            pclassName = ftype.asString();
                            psimpleName = replacePackageName(ftype.asString());
                            type = ftype;
                            ApiField field2 = handleParamType(type, null);
                            type = field2.getParamType();
                            pclassName = field2.getClassName();
                            psimpleName = field2.getSimpleName();
                            showType = field2.getShowType();
                            field.setAnonymousFlag(field2.getAnonymousFlag());
                            field.setSimpleValueFlag(field2.getSimpleValueFlag());
                            field.setChildren(field2.getChildren());
                        }
                    }
                }else {
                    showType = psimpleName;
                    field.setSimpleValueFlag(true);
                }
            }
        } 
        else {
            showType = type.asString();
        } 
        
        field.setParamType(type);
        field.setClassName(pclassName);
        field.setSimpleName(psimpleName);
        field.setShowType(showType);
        field.setFactType(showType);
        return field;
    }
    
    private static void handleMergeParamTag(ApiAction apiAction, Map<String, ApiField> paramsFactNameMap) {
        List<ApiField> tParams = getParams(apiAction.getDocTags());//入参
        List<ApiField> tParamObjs = getParamObjs(apiAction.getDocTags());//入参
        List<ApiField> tRespParams = getResp(apiAction.getDocTags());//出参
        ApiField tReturnObj = getSeeObj(apiAction.getDocTags());//出参
        
        List<ApiField> reqParam = apiAction.getReqParam();
        List<ApiField> resParam = apiAction.getResParam();
        
        for(ApiField px:tParams){
            ApiField factField = paramsFactNameMap.get(px.getName());
            if(factField!=null){
                px.setName(factField.getName());
                if(StringUtils.isNotBlank(px.getTitle())) {
                    factField.setTitle(px.getTitle());
                    factField.setDescription(px.getDescription());
                }
                if(StringUtils.isNotBlank(px.getDefaultValue())) {
                    factField.setDefaultValue(px.getDefaultValue());
                }
            }else {
                reqParam.add(px);
            }
        }
        for(ApiField px:tParamObjs){
            ApiField factField = paramsFactNameMap.get(px.getName());
            if(factField!=null){
                px.setName(factField.getName());
                if(StringUtils.isNotBlank(px.getTitle())) {
                    factField.setTitle(px.getTitle());
                    factField.setDescription(px.getDescription());
                }
                if(StringUtils.isNotBlank(px.getDefaultValue())) {
                    factField.setDefaultValue(px.getDefaultValue());
                }
            }else {
                reqParam.add(px);
            }
        }
        for(ApiField px:tRespParams){
            List<ApiField> children = resParam.get(0).getChildren();
            boolean flag = false;
            if(!children.isEmpty()) {
                for(ApiField factField:children) {
                    if(px.getFactName().equals(factField.getFactName())) {
                        if(StringUtils.isNotBlank(px.getTitle())) {
                            factField.setTitle(px.getTitle());
                            factField.setDescription(px.getDescription());
                        }
                        if(StringUtils.isNotBlank(px.getDefaultValue())) {
                            factField.setDefaultValue(px.getDefaultValue());
                        }
                        flag = true;
                        break;
                    }
                }
            }
            if(!flag) {
                children.add(px);
            }
        }
        if(tReturnObj != null) {
            List<ApiField> tchildren = tReturnObj.getChildren();
            List<ApiField> children = resParam.get(0).getChildren();
            for(ApiField px:tchildren){
                boolean flag = false;
                if(!children.isEmpty()) {
                    for(ApiField factField:children) {
                        if(px.getFactName().equals(factField.getFactName())) {
                            if(StringUtils.isNotBlank(px.getTitle())) {
                                factField.setTitle(px.getTitle());
                                factField.setDescription(px.getDescription());
                            }
                            if(StringUtils.isNotBlank(px.getDefaultValue())) {
                                factField.setDefaultValue(px.getDefaultValue());
                            }
                            flag = true;
                            break;
                        }
                    }
                }
                if(!flag) {
                    children.add(px);
                }
            }
        }
    }
    private static void handleIgnoreParam(List<ApiField> fields) {
        if(fields==null || fields.isEmpty()) {
            return;
        }
        Iterator<ApiField> iterator = fields.iterator();
        ApiField px;
        while(iterator.hasNext()) {
            px = iterator.next();
            if(px.getHiddenFlag()) {
                iterator.remove();
            }else {
                handleIgnoreParam(px.getChildren());
            }
        }
    }
    
}
